export function equalbyte(a, b) {
	return (a & 0xFF) == (b & 0xFF)
}
export function equalbytes(arr, brr) {
	if (arr == null || brr == null) return false;
	if (arr.length == brr.length) {
		for (var i = 0; i < arr.length; i++) {
			if (arr[i] != brr[i]) return false;
		}
	}
	return true;
}
/**
 *  拼接Uint8Array
 * @return {Uint8Array}
 */
export function concatUi8Arr(...arrays) {
	let totalLen = 0;
	for (let arr of arrays) {
		if (arr == undefined) continue;
		totalLen += arr.length;
		//console.log(totalLen,arr,arr.length)
	}
	let res = new Uint8Array(totalLen);

	let offset = 0
	for (let arr of arrays) {
		if (arr == undefined) continue;
		res.set(arr, offset);
		offset += arr.length;
	}
	return res;
}
/**
 *  拼接arraybuffer
 * @return {arraybuffer}
 */
export function concatBuf(...arrays) {
	let totalLen = 0;
	for (let arr of arrays) {
		if (arr == undefined) continue;
		totalLen += arr.byteLength;
	}
	let res = new Uint8Array(totalLen)
	let offset = 0
	for (let arr of arrays) {
		if (arr == undefined) continue;
		let uint8Arr = new Uint8Array(arr)
		res.set(uint8Arr, offset)
		offset += arr.byteLength
	}
	return res.buffer;
}

/**
 * @param {Uint8Array} bytes 
 */
export function subBytes(arr, start, len) {
	return new Uint8Array(arr.buffer, start, len);

}

export function getHash(bytes) {
	// 1315423911=b'1001110011001111100011010100111'
	var hash = 1315423911,
		i, ch;
	for (i = bytes.length - 1; i >= 0; i--) {
		ch = bytes[i];
		hash ^= ((hash << 5) + ch + (hash >> 2));
	}
	return (hash & 0x7FFFFFFF);
}

/**
 * 非中文bytes 数组转字符串
 * @param {Uint8Array} fileData 
 * @return {String}
 */
export function Ui8ToAscii(fileData) {
	var dataString = "";
	for (var i = 0; i < fileData.length; i++) {
		dataString += String.fromCharCode(fileData[i]);
	}
	return dataString

}
/**
 * 非中文字符串转 Uint8Array
 * @param {String} str 
 * @return {Uint8Array}
 */
export function AsciiToUi8(str) {
	let outputArray = new Uint8Array(str.length);
	for (var i = 0; i < str.length; ++i) {
		outputArray[i] = str.charCodeAt(i);
	}
	return outputArray;
}

/**
 * str2ab(str)的参数是 String,转换的结果是 ArrayBuffer
 * @param {String} str 
 */
export function strToUi16(str) {
	//var buf = new ArrayBuffer(str.length * 2); // 每个字符占用2个字节
	var bufView = new Uint16Array(str.length);
	for (let i = 0, strLen = str.length; i < strLen; i++) {
		bufView[i] = str.charCodeAt(i);
	}
	return bufView;
}
/**
 * Uint16Array 转 string
 * @param {Uint16Array} buf 
 */
export function Ui16Tostr(buf) {
	/*Int8Array：8位有符号整数，长度1个字节。
	    Uint8Array：8位无符号整数，长度1个字节。
	    Int16Array：16位有符号整数，长度2个字节。
	    Uint16Array：16位无符号整数，长度2个字节。
	    Int32Array：32位有符号整数，长度4个字节。
	    Uint32Array：32位无符号整数，长度4个字节。
	    Float32Array：32位浮点数，长度4个字节。
	    Float64Array：64位浮点数，长度8个字节。*/
	var list = "";
	for (var i = 0; i < buf.length; i++) {
		list += String.fromCharCode(buf[i]);
	}
	return list;
}

/**
 * byte数组转换为无符号short整数
 * @param {*} bytes 
 * @param {*} off 
 */
export function byte2ToUShort(bytes, off) {
	off = off | 0;
	var high = bytes[off + 1];
	var low = bytes[off];
	return (high << 8 & 0xFF00) | (low & 0xFF);
}

/**
 * 无符号short转换为2字节的byte数组
 * @param {*} s 
 */
export function unShortToByte2(s) {
	var targets = [];
	targets[1] = (s >> 8 & 0xFF);
	targets[0] = (s & 0xFF);
	return new Uint8Array(targets);
}
//byte数组转换为int整数
/**
 * @param {Array|ArrayBuffer} bytes
 * @param {Object} off
 */
export function byte4ToInt(bytes, off) {
	off = off | 0;
	var b0 = bytes[off] & 0xFF;
	var b1 = bytes[off + 1] & 0xFF;
	var b2 = bytes[off + 2] & 0xFF;
	var b3 = bytes[off + 3] & 0xFF;
	//console.log(b0,b1,b2,b3)
	return (b0 << 24) | (b1 << 16) | (b2 << 8) | b3;
}

/**
 * int整数转换为4字节的byte数组
 * @param {*} i 
 */
export function intToUi8Arr(i) {
	return new Uint8Array(intToByte4(i));
}
export function intToByte4(i) {
	var targets = [];
	targets[0] = (i >> 24 & 0xFF);
	targets[1] = (i >> 16 & 0xFF);
	targets[2] = (i >> 8 & 0xFF);
	targets[3] = (i & 0xFF);
	return targets;
}
//有符int转无符int
export function int2uint(i) {
	if (i >= 0)
		return i;
	else
		4294967296 + i;
}

/**
 * 无符int转有符int
 * @param {*} i 
 */
export function uint2int(i) {
	if (i <= 2147483647)
		return i;
	else
		return i - 4294967296
}
/**
 * 有符char转无符char
 */
export function char2uchar(i) {
	if (i >= 0)
		return i;
	else
		65535 + i;
}

/**
 * 无符char转有符char
 * @param {*} i 
 */
export function uchar2char(i) {
	if (i <= 32767)
		return i;
	else
		return i - 65535
}

/**
 * 有符byte转无符byte
 * @param {*} i 
 */
export function bytes2ubytes(i) {
	if (i >= 0)
		return i;
	else
		255 + i;
}

/**
 * 无符byte转有符byte
 * @param {*} i 
 */
export function ubytes2bytes(i) {
	if (i <= 127)
		return i;
	else
		return i - 255
}

/**
 * 
 * @param {Object} obj 
 * @return {Uint8Array} 
 */
export function json2Bytes(obj) {
	let str = JSON.stringify(obj)
	//return new TextEncoder('utf-8').encode(str);
	return strToUtf8Array(str)
}
/**
 * 
 * @param {Uint8Array} bytes  入参必须是Uint8Array类型 不能是 ArrayBuffer
 * @return {Object}
 */
export function bytes2Json(bytes) {


	let str = Utf8ArrayToStr(bytes);
	//console.log("bytes2Json1:",bytes.byteLength,str)
	//let str = new TextDecoder('utf-8').decode(bytes);
	//console.log("bytes2Json2:",str)
	return JSON.parse(str)
}


// var obj = { kdkd: 29, "看得开": [2, 4, 65], f3: false, f4: 0 }
// var b1 = json2bytes(obj)
// console.log(b1)
// var o1 = bytes2Json(b1)
// console.log(o1)

/**
 * 判断系统的整型字节高低位顺序
 */
export function littleEndian() {
	var buffer = new ArrayBuffer(2);
	new DataView(buffer).setInt16(0, 256, true);
	return new Int16Array(buffer)[0] === 256;
}

/**
 * 字符串 to utf8 编码 bytes 支持中文 
 * 等效于 nodejs/fun.js 中的 Utf8ToBuffer
 * @param {String} string 
 * @param {*} options 
 * @return {Uint8Array}
 */
export function strToUtf8Array(string) {

	if (string == null) return null;
	let pos = 0;
	const len = string.length;
	const out = [];

	let at = 0; // output position
	let tlen = Math.max(32, len + (len >> 1) + 7); // 1.5x size
	let target = new Uint8Array((tlen >> 3) << 3); // ... but at 8 byte offset

	while (pos < len) {
		let value = string.charCodeAt(pos++);
		if (value >= 0xd800 && value <= 0xdbff) {
			// high surrogate
			if (pos < len) {
				const extra = string.charCodeAt(pos);
				if ((extra & 0xfc00) === 0xdc00) {
					++pos;
					value = ((value & 0x3ff) << 10) + (extra & 0x3ff) + 0x10000;
				}
			}
			if (value >= 0xd800 && value <= 0xdbff) {
				continue; // drop lone surrogate
			}
		}
		// expand the buffer if we couldn't write 4 bytes
		if (at + 4 > target.length) {
			tlen += 8; // minimum extra
			tlen *= (1.0 + (pos / string.length) * 2); // take 2x the remaining
			tlen = (tlen >> 3) << 3; // 8 byte offset

			const update = new Uint8Array(tlen);
			update.set(target);
			target = update;
		}

		if ((value & 0xffffff80) === 0) { // 1-byte
			target[at++] = value; // ASCII
			continue;
		} else if ((value & 0xfffff800) === 0) { // 2-byte
			target[at++] = ((value >> 6) & 0x1f) | 0xc0;
		} else if ((value & 0xffff0000) === 0) { // 3-byte
			target[at++] = ((value >> 12) & 0x0f) | 0xe0;
			target[at++] = ((value >> 6) & 0x3f) | 0x80;
		} else if ((value & 0xffe00000) === 0) { // 4-byte
			target[at++] = ((value >> 18) & 0x07) | 0xf0;
			target[at++] = ((value >> 12) & 0x3f) | 0x80;
			target[at++] = ((value >> 6) & 0x3f) | 0x80;
		} else {
			// FIXME: do we care
			continue;
		}

		target[at++] = (value & 0x3f) | 0x80;
	}

	return target.slice(0, at);
}

/**
 * Uint8Array 转 String 支持中文
 * 等效于 nodejs/fun.js 中的 BufferToUtf8
 * @param {Uint8Array} array  不能是 arraybuffer 必须是Uint8Array
 * @return {String}
 */
export function Utf8ArrayToStr(array) {
	if (array == null) return null;
	var out, i, len, c;
	var char2, char3;
	out = "";
	len = array.length;
	i = 0;
	while (i < len) {
		c = array[i++];
		switch (c >> 4) {
			case 0:
			case 1:
			case 2:
			case 3:
			case 4:
			case 5:
			case 6:
			case 7:
				// 0xxxxxxx
				out += String.fromCharCode(c);
				break;
			case 12:
			case 13:
				// 110x xxxx   10xx xxxx
				char2 = array[i++];
				out += String.fromCharCode(((c & 0x1F) << 6) | (char2 & 0x3F));
				break;
			case 14:
				// 1110 xxxx  10xx xxxx  10xx xxxx
				char2 = array[i++];
				char3 = array[i++];
				out += String.fromCharCode(((c & 0x0F) << 12) |
					((char2 & 0x3F) << 6) |
					((char3 & 0x3F) << 0));
				break;
		}
	}

	return out;
}

/**
 * 
 * @param {ArrayBuffer} buffer 
 */
export function BufferToBase64(buffer) {
	return String.fromCharCode(...new Uint8Array(buffer))
}
/**
 * 
 * @param {String} base64str 
 */
export function Base64ToBuffer(base64str) {
	const byteLength = base64str.length;
	const bytes = new Uint8Array(byteLength);
	for (let i = 0; i < byteLength; i++) {
		bytes[i] = base64str.charCodeAt(i);
	}
	return bytes.buffer;
}

export function blob2Buffer(blob, fun) {
	if (fun&&blob){
		let reader = new FileReader();
		reader.onload = function(e) {
			//console.log(e,this.result)
			if (this.result)
				fun( new Uint8Array(this.result));
		}
		reader.readAsArrayBuffer(blob);		
	}
}
export function buffer2Blob(buff) {
	return new Blob([buff])
}
